----------------------------------------------------------------------
--- Common extensions to the base functionality

if not __DO_ONCE__ then
  __DO_ONCE__ = true
  --Modify module paths
  package.path = package.path..";.\\?.lua;.\\?\\?.lua"
  package.cpath = package.cpath..";.\\?.dll;.\\?\\?.dll"
end

if __DEV__ then
  --override "require" with a version that always reloads modules
  --this gives us fast iteration for modules, and improves development speed
  truerequire = truerequire or require
  local dontreload = {
    string = true,
    math   = true,
    table  = true,
    io     = true,
    os     = true,
    debug  = true,
  }   
  function require(name)
    if dontreload[name] ~= true then 
      package.loaded[name]=nil
      truerequire(name)
      print("loaded module",name)
    end
  end
else  
  truerequire = truerequire or require  
end

--- boolean aliases to aid code readability
off = false
on  = true
yes = true
no  = false

--- Bring commonly used module functions to the global namespace
rand   = math.random
format = string.format
tolower  = string.lower
toupper  = string.upper

--- Print formated string
function printf(s,...)
  print(format(s,...))
end

if __DEBUG__ then
  debug.assert = assert
  debug.print  = print
  debug.printf = printf  
else
  --Ignore asserts
  dummy = function(...) return true end
  debug.assert = dummy
  debug.print  = dummy
  debug.printf = dummy  
end

printd = debug.print

log = printf


--- A function that does nothing
nullfunction = function(...)end

--- Extended type definitions
local truetype = truetype or type -->without this check when quick iteration 
                            -- is on this might cause the new type function 
                            -- to be referencing itself causing an infinite 
                            -- loop 
function type(v)
  local v = v
  local s = truetype(v)
  if s == "table" or s == "userdata" then
    if v.__type then
      s = v.__type
    end 
  end
  return s
end 

--debug = debug or {}
debug.func = {
  name = {
    this = function()
      local t = debug.getinfo(2)
      return format("%s[%s]",t.name,t.namewhat)
    end,
    prev = function()
      local t = debug.getinfo(3)
      return format("%s[%s]",t.name,t.namewhat)
    end,
  }, 
  location = {
    this = function()
      local t = debug.getinfo(2)
      return format("%s[line:%s]",t.source,t.linedefined)
    end,
    prev = function()
      local t = debug.getinfo(3)
      return format("%s[line:%s]",t.source,t.linedefined)
    end,
  },
  call = {
    this = function()
      local t = debug.getinfo(2,'f')
      return t.func
    end,
    prev = function()
      local t = debug.getinfo(3,'f')
      return t.func
    end,   
   },
   trace = function()
     return debug.traceback()
   end,
}

--- Make the program wait
function wait(seconds)
  local socket = socket or require"socket"
  if socket then
    socket.sleep(seconds)
  else -- We can't find the socket module so we busy sleep instead 
    debug.print("Couldn't find the socket module. Doing a busy wait instead")
    local t = os.time() + seconds
    while (os.time() < t) do
    end
  end
end

--- Clone tables, as opposed to referencing them
clone = function(t)
  local u = setmetatable ({}, getmetatable (t))
  local k,v
  for k, v in pairs (t) do
    if truetype(v)=="table" then
      if v ~= t then -->avoid cycles
        u[k] = clone(v)-->recursively clone subtables
      end
    else
      u[k] = v
    end
  end
  return u
end


--- Wrapup a function to use memoization
if __OPTIMIZE__ then
  function memoize (fun)
    local __results ={}
    setmetatable(__results, {__mode = "kv"})  
    return function(s)
      if __results[s]~=nil then
        return __results[s]
      else
        local v = fun(s)
        __results[s] = v
        return v 
      end
    end
  end
else
  function memoize (fun)
    return fun
  end
end      

--- Extended require, that brings everything from a module or table into the global namespace
function using(t)
  local t = t
  if type(t) == "string" then
    t = require(t)
  end
  local k,v 
  for k,v in pairs(t) do
    if _G[k] ~= nil then 
      log("redefinition of global "..k)
    end 
	_G[k] = _G[k] or v  -- don't overwrite existing variables
  end
end

--> Weak table
local weaktable_mt = {__mode="k"}

function weaktable(t)
  local t = t or {}
  setmetatable(t,weaktable_mt)
  return t
end

--> Readonly table
local readonly_mt = {
  __index = function(t,k)
    return t.__readonly[k]
  end,  
  __newindex = function (t,k,v)
    error("attempt to update a read-only table", 2)
  end
}

function readonly (t)
  local ro ={}
  ro.__readonly = t
  setmetatable(ro, readonly_mt)
  return ro
end

final_mt = {
  __newindex = function (t,k,v)
    error("attempt to update a read-only table", 2)
  end
}

function final (t)
  setmetatable(t, final_mt)
  return t
end

function has(list,v)  -->Check if an array has a value
  local i,t
  local list = list
  for i,t in pairs(list) do
    if t == v then 
      return t 
    end
  end
  return nil
end

function compare(s1,s2)
  if s2 == "" then
    return false
  end
  local s2 =s2
  if s2 == "*" then
    s2 = ".+" -->Match anything,except empty strings
  end
  if (string.find(tolower(s1),tolower(s2)) ~= nil) or (string.find(tolower(s2),tolower(s1)) ~= nil) then
    return true
  else
    return false
  end    
end


function string.explode(s)
 local words = {}
 string.gsub(s, "([%p%w]+)", function (w)
   table.insert(words, w)
 end)
 return words
end

function string.trim (s)
  return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end

function string.expand (s)
  s = string.gsub(s, "$(%w+)", function (n)
        return tostring(tokens[n])
      end)
  return s
end

function r(s)
  return string.format("%q",s)
end

function filter(fun, t)
  local r = {}
  for k,v in ipairs(t) do 
    if fun(t[k]) then
      table.insert(r,v)
    end
  end
  return r
end
--  t = filter(function(x) if x=1 then return false else return true end end,{1,2,3}) --> map(print,t) --> 2,3
function map(fun,t)
  for k,v in ipairs(t) do
    t[k] = fun(v)
  end
  return t
end

--t = map(function(x) return x*x*x end, {1,2,3})  --> map(print,t) --> {1,8,27}
function reduce(fun,t)
  local r,i=nil,1
  r = r or t[1]
  while #t > i do
    i = i +1
    r = fun(r,t[i])
  end
  return r
end
--reduce(function(x,y) return x+y end,{1,2,3,4,5,6,7,8,9,10}) --> 55

function symbol(s)
  local new = s
  local old = _G[s]
 _G[s]= old or new
 if old ~= new then
   error(string.format("symbol %q has already been defined by %q",new,old))
 end
 return new
end

s = symbol
--s"LALA" --> print(LALA)=LALA
